//go:build ignore
// +build ignore

package main

import (
	"fmt"
	"log"
	"math"

	"gitee.com/nggs/golang/util"
)

/***********************************************************************************************************************
// 借鉴以下代码实现基于正态随机的权重掉落

import numpy as np
import matplotlib.pyplot as plt

np.random.seed(0)

N= 50000
wt = [20, 30, 50 ]
wtp = [1.*x/sum(wt) for x in wt]
result = []
p = [np.random.normal( 1./x, 1./x/3.) for x in wtp]
for i in xrange(N):
    minp = 1.e9
    minj = -1
    for j, pp in enumerate(p):
        if pp < minp:
            minp = pp
            minj = j
    result.append(minj)
    for j, pp in enumerate(p):
        p[j] -= minp
    p[minj] = np.random.normal(1./wtp[minj], 1./wtp[minj]/3.)

1. 先对所有物品按权值进行正太分布随机，每次取出 掉落间隔最小的物品, 也就是最先出现的( result <- item index ) ，然后其他物品均减去该间隔值
2. 被取出的物品 再单独进行一次正太分布随机，获得新的掉落间隔
3. goto step 1
***********************************************************************************************************************/

func GenRandomRatesInt(weights map[int]int) (rates map[int]float64, err error) {
	if len(weights) == 0 {
		err = fmt.Errorf("weights is empty")
		return
	}

	var totalWeight int
	for _, w := range weights {
		if w <= 0 {
			continue
		}
		totalWeight += w
	}
	if totalWeight <= 0 {
		err = fmt.Errorf("total weight is 0")
		return
	}

	rates = map[int]float64{}
	for i, weight := range weights {
		if weight <= 0 {
			continue
		}
		rates[i] = float64(weight) / float64(totalWeight)
	}

	return
}

func NormalDiscreteDistributionInt(rawRates map[int]float64, randomRates map[int]float64) (map[int]float64, int, error) {
	if len(rawRates) == 0 {
		return nil, 0, fmt.Errorf("raw rates is empty")
	}

	if len(randomRates) == 0 {
		if randomRates == nil {
			randomRates = map[int]float64{}
		}
		for i, rate := range rawRates {
			randomRates[i] = util.NormalDistributionRandom(1.0/rate, 1.0/rate/3.0)
		}
	}

	var minRate = math.MaxFloat64
	var hit int
	for i, rate := range randomRates {
		if rate < minRate {
			minRate = rate
			hit = i
		}
	}
	for i, _ := range randomRates {
		randomRates[i] -= minRate
	}

	randomRates[hit] = util.NormalDistributionRandom(1.0/rawRates[hit], 1.0/rawRates[hit]/3.0)

	return randomRates, hit, nil
}

func main() {
	var weights = map[int]int{1: 50, 2: 30, 3: 19, 4: 0, 5: 1}
	var rawRates, _ = GenRandomRatesInt(weights)

	var randomRates map[int]float64
	var hit int
	var hits = map[int]int{}
	for i := 0; i < 1000000; i++ {
		randomRates, hit, _ = NormalDiscreteDistributionInt(rawRates, randomRates)
		hits[hit] += 1
	}

	log.Printf("hits=%v\n", hits)
}
